//
//  std::make_unique_ptr.hpp
//  learnC++
//
//  Created by liuzhibing on 2018/6/30.
//  Copyright © 2018年 yunfan.com. All rights reserved.
//

#ifndef std__make_unique_ptr_hpp
#define std__make_unique_ptr_hpp

#include <stdio.h>
#include <iostream>
#include <memory>

/*
 有两种简单的方法来滥用std :: unique_ptrs，这两个都很容易避免。 首先，不要让多个类管理相同的资源。 例如：
 Resource *res = new Resource;
 std::unique_ptr<Resource> res1(res);
 std::unique_ptr<Resource> res2(res);
 其次，不要从std :: unique_ptr下手动删除资源。
 Resource *res = new Resource;
 std::unique_ptr<Resource> res1(res);
 delete res;
 请注意，std :: make_unique（）可以防止上述两种情况无意中发生。
 */

class Fraction6 {
private:
    int m_numerator = 0;
    int m_denominator = 1;
    
    
public:
    Fraction6(int numerator = 0,int denominator = 1):m_numerator(numerator),m_denominator(denominator){
        std::cout << "init\n";
    }
    ~Fraction6(){
        std::cout << "dealloc\n";
    }
    
    friend std::ostream &operator<<(std::ostream &out,const Fraction6 &f1){
        out << f1.m_numerator << "/" << f1.m_denominator;
        return out;
    }
    
    std::unique_ptr<Fraction6> creatObject()
    {
        
//        creatObject（）按值返回一个std :: unique_ptr。 如果此值未分配给任何内容，则临时返回值将超出范围，资源将被清理。 如果它被赋值（如main（）所示），将使用移动语义将资源从返回值传递给分配给的对象（在上例中为ptr）。 这使得通过std :: unique_ptr返回资源比返回原始指针更安全！
        return std::make_unique<Fraction6>();
    }
    
    //std::unique_ptr作为参数(此时因为传递时是值传递，需要std::move来指定移动语义)
    std::unique_ptr<Fraction6> takeOwnership(std::unique_ptr<Fraction6> res){
        if (res) {
            std::cout << *res;
        }
        return res;
    }
    
    //使用std::unique_ptr.get()方法 \ 要从std :: unique_ptr获取原始资源指针，可以使用get（）成员函数：
    void printSelf(Fraction6 *res){
        if (res) {
            std::cout << *res;
        }
    }
    
};

/*
 //使用std::make_unique传递初始化参数
 std::unique_ptr<Fraction6> f1 = std::make_unique<Fraction6>(3,5);
 std::cout << *f1 << "\n";
 
 std::unique_ptr<Fraction6> f2 = std::unique_ptr<Fraction6>(new Fraction6(6,8));
 std::cout << *f2 << "\n";
 
 auto f3 = std::make_unique<Fraction6[]>(4);
 std::cout << f3[0] << "\n";
 
 规则：使用std :: make_unique（）而不是创建std :: unique_ptr并自己使用new
 
 */

#endif /* std__make_unique_ptr_hpp */
